/**
 * Copyright 2018 人人开源 http://www.renren.io
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.dhh.web.common.shiro;


import com.dhh.web.common.exception.BusinessException;
import com.dhh.web.common.utils.Constant;
import com.dhh.web.modules.user.domain.Perms;
import com.dhh.web.modules.user.domain.Role;
import com.dhh.web.modules.user.domain.User;
import com.dhh.web.modules.user.repo.PermsRepo;
import com.dhh.web.modules.user.repo.UserRepo;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Set;

/**
 * 认证
 *
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2016年11月10日 上午11:55:49
 */
@Component
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserRepo userRepo;
    @Autowired
    private PermsRepo permsRepo;

    /**
     * 授权(验证权限时调用)
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        User user = (User) principals.getPrimaryPrincipal();
        String userId = user.getUserId();

        Set<Perms> permsList = new HashSet<>();

        //系统管理员，拥有最高权限
        if (Constant.SUPER_ADMIN_ID.equals(userId)) {
            permsList = new HashSet<>(permsRepo.findAll());
        } else {
            Set<Role> roleList = userRepo.findById(userId).orElseThrow(() -> new BusinessException("通过id没有找到用户")).getRoles();
            Set<Perms> finalPermsList = permsList;
            roleList.forEach(role -> finalPermsList.addAll(role.getPerms()));
        }
        //用户权限列表
        Set<String> permsSet = new HashSet<>();
        permsList.forEach(perms -> permsSet.add(perms.getName()));
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(permsSet);
        return info;
    }

    /**
     * 认证(登录时调用)
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken authcToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
        //查询用户信息
        User user = userRepo.findByUsername(token.getUsername()).orElseThrow(() -> new UnknownAccountException("账号或密码不正确"));
        //账号锁定
        if (user.getStatus() == 0) {
            throw new LockedAccountException("账号已被锁定,请联系管理员");
        }
        return new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes(user.getSalt()), getName());
    }

    @Override
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        HashedCredentialsMatcher shaCredentialsMatcher = new HashedCredentialsMatcher();
        shaCredentialsMatcher.setHashAlgorithmName(ShiroUtils.hashAlgorithmName);
        shaCredentialsMatcher.setHashIterations(ShiroUtils.hashIterations);
        super.setCredentialsMatcher(shaCredentialsMatcher);
    }
}
